package com.xplay.xpocker.service.system.impl;

import com.xplay.xpocker.business.BusinessEnum;
import com.xplay.xpocker.mapper.SysUserMapper;
import com.xplay.xpocker.meta.MessageContent;
import com.xplay.xpocker.meta.realize.MahjongUserChannel;
import com.xplay.xpocker.meta.room.MetaRoomEntity;
import com.xplay.xpocker.meta.rule.MetaRoomRule;
import com.xplay.xpocker.meta.user.MetaUserChannel;
import com.xplay.xpocker.service.mahjong.IRoomService;
import com.xplay.xpocker.service.mahjong.impl.DiskPartServiceImpl;
import com.xplay.xpocker.socket.UserChannelMate;
import com.xplay.xpocker.util.BusinessAssertion;
import com.xplay.xpocker.util.DictionaryConst;
import com.xplay.xpocker.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author wanjie
 * @date 2021/3/28 16:23
 */
@Service
public class RoomServiceImpl implements IRoomService, UserChannelMate {

    private static Logger log = LoggerFactory.getLogger(RoomServiceImpl.class);
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    @Resource
    private SysUserMapper sysUserMapper;

    @Override
    public MetaRoomEntity queryRoomInfo(String roomCode) {
        MetaRoomEntity roomEntity = (MetaRoomEntity) redisUtil.get(DictionaryConst.RedisHeader.ROOM_HEADER + roomCode);
        return roomEntity;
    }

    @Override
    public void saveRoomInfo(MetaRoomEntity roomEntity) {
        redisUtil.set(DictionaryConst.RedisHeader.ROOM_HEADER + roomEntity.getCode(), roomEntity, DictionaryConst.RedisExpireData.ROOM_EXPIRE);
    }

    @Override
    public void roomUserOnline(String roomCode, String userId, boolean online) {
        log.info("=======用户======{}======{}", userId, online ? "上线" : "离线");
        MetaRoomEntity<MetaRoomEntity, MetaRoomRule, MetaUserChannel> roomEntity = (MetaRoomEntity<MetaRoomEntity, MetaRoomRule, MetaUserChannel>) redisUtil.get(DictionaryConst.RedisHeader.ROOM_HEADER + roomCode);
        if (null != roomEntity && roomEntity.getAllUserInfo() != null) {
            MetaUserChannel userChannel = roomEntity.getAllUserInfo().get(userId);
            if (userChannel != null) {
                userChannel.setOnline(online);
            }
            saveRoomInfo(roomEntity);
        }
    }

    @Override
    public MetaRoomEntity addRoom(String roomCode, String userId) {
        ArrayList<Integer> userSeqList = new ArrayList<>();
        ArrayList<Integer> allSeqList = new ArrayList<>();
        MetaRoomEntity roomHistory = queryUserRoom(userId);
        MetaRoomEntity<MetaRoomEntity, MetaRoomRule, MetaUserChannel> roomEntity = (MetaRoomEntity<MetaRoomEntity, MetaRoomRule, MetaUserChannel>) redisUtil.get(DictionaryConst.RedisHeader.ROOM_HEADER + roomCode);
        BusinessAssertion.isNull(BusinessEnum.ROOM_NOT_FOUND, roomEntity);
        BusinessAssertion.isTrue(BusinessEnum.ROOM_ON_MORE, roomHistory != null && roomHistory.getDbSequence().equals(roomEntity.getDbSequence()));
        int userCount = roomEntity.getRoomRule(MetaRoomRule.class).getUserCount();
        HashMap<String, MetaUserChannel> allUserInfo = roomEntity.getAllUserInfo();
        if (allUserInfo == null) {
            allUserInfo = new HashMap<String, MetaUserChannel>();
            roomEntity.setAllUserInfo(allUserInfo);
        } else {
            allUserInfo.forEach((itemUid, itemUinfo) -> {
                userSeqList.add(itemUinfo.getSeq());
            });
        }
        for (Integer i = 1; i <= userCount; i++) {
            allSeqList.add(i);
        }

        MetaUserChannel metaUserChannel = allUserInfo.get(userId);
        Integer seq = null;
        if (metaUserChannel == null) {
            BusinessAssertion.isTrue(BusinessEnum.ROOM_FULL, userCount == allUserInfo.size());
            List<Integer> notSeqList = allSeqList.stream().filter(val -> !userSeqList.contains(val)).collect(Collectors.toList());
            Collections.sort(notSeqList);
            // 如果是新玩家 序列加1
            seq = notSeqList.get(0);
            boolean isBanker = false;
            boolean homeowners = false;
            if (seq == 1) {
                isBanker = true;
                homeowners = true;

            }
            metaUserChannel = new MahjongUserChannel(userId, null, isBanker, seq, false, false, homeowners);
            metaUserChannel.setSysUser(sysUserMapper.selectByName(userId));
            allUserInfo.put(userId, metaUserChannel);
        }
        saveRoomInfo(roomEntity);
        // 这里有可能需要清理变量  UserChannelMate ----  diskPart  订阅对象 当房间销毁了  应该remove
        redisUtil.set(DictionaryConst.RedisHeader.USER_ROOM_HEADER + userId, roomCode);
        return roomEntity;
    }

    @Override
    public MetaRoomEntity queryUserRoom(String userId) {
        Object roomCodeObject = redisUtil.get(DictionaryConst.RedisHeader.USER_ROOM_HEADER + userId);
        if (roomCodeObject == null) {
            return null;
        }
        String roomCode = roomCodeObject.toString();
        MetaRoomEntity roomEntity = (MetaRoomEntity) redisUtil.get(DictionaryConst.RedisHeader.ROOM_HEADER + roomCode);
        if (roomEntity == null) {
            // 移除房间所有的订阅对象
            exitRoom(userId);
            diskPart.remove(roomCode);
        }
        return roomEntity;
    }

    @Override
    public void exitRoom(String userId) {
        redisUtil.del(DictionaryConst.RedisHeader.USER_ROOM_HEADER + userId);
    }

    @Override
    public void delRoomInfo(String roomCode) {
        redisUtil.del(DictionaryConst.RedisHeader.ROOM_HEADER + roomCode);
        diskPart.remove(roomCode);
    }
}
